from base.util import *


def filter_dec(prefix):
    def d01(func):
        @wraps(func)
        def d02(self, *args, **kwargs):
            if (self.tag == "any") and (not prefix.startswith("by value")):
                return True  # any标签
            flag = func(self, *args, **kwargs)
            if not flag:
                if "procName" in prefix:
                    msg = f"{prefix}[{self.procName}] {self.line}"
                else:
                    msg = f"{prefix}{self.line}"
                self.excludeS.append(msg)
            return flag

        return d02

    return d01


class AutoComple:

    @filter_dec("by procName: ")
    def filter_white_list(self, tag: str):
        tag = tag.replace("c#", "cc")
        white_list_d = {
            # "标签" : "白名单",
            "sql": "Code navicat",
            "python": "Code pycharm64",
            "anki": "anki",
            "cc": "Quicker Code",  # "c#"标签
        }
        if tag in white_list_d.keys():
            flag = (self.procName in white_list_d[tag].split()) \
                   and 1 or 0
        else:
            flag = 1
        return flag

    @filter_dec("by Special: ")
    def filter_Special(self, tag):
        """特殊筛选
        1.在PyCharm进程中, 只能使用python标签、正则标签、any标签
        2.如果是stop标签, 则忽略
        """
        if self.procName == "pycharm64":
            flag = (tag in "python 正则".split()) \
                   and 1 or 0
        else:
            flag = 0 if (tag == "stop") else 1
        return flag

    @filter_dec("by value: ")
    def filter_other(self, value: str):
        """
        【对value筛选排除】
         pattern: 正则表达式, 可以写多个, 匹配则排除
        当前排除内容:
            quicker动作id/动作uri(包含匹配)
            连续的中文数>=7位的,
            排除各种链接
            anki进程的
        )
        """
        # 仅排除value, 根据其他规则
        patternS = [
            r"[a-z\d]{8}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{12}",
            r"^quicker:runaction",
            r"[\u4e00-\u9fa5]{7,}",
            r"(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]"]
        if any(re.search(pat, value.strip())
               for pat in patternS):
            return 0
        return 1

    @filter_dec("by key: ")
    def filter_key(self, key):
        if key:
            return 1
        else:
            return 0

    def __init__(self, s, procName=""):
        self.dict_ = {}
        self.valueS = []
        self.excludeS = []
        self.procName: str = procName
        self.line = ""
        self.tag: str = ""
        self.li = s.strip().splitlines()

    def run(self) -> dict:
        self.main()
        keys = "dict_ valueS excludeS".split()
        values = self.dict_, self.valueS, self.excludeS
        res = dict(zip(keys, values))
        # cc(self.excludeS)
        return res

    def main(self):
        _1_ = "|||"  # key,value分隔符
        for line in self.li:
            if "提取key,value,tag":
                self.line: str = line
                try:
                    key, value_tag = line.split(_1_, 1)
                    value, tag = value_tag.rsplit("##", 1)
                    self.tag = tag = tag.rstrip("\\")  # 不知道为什么就是多出一个反斜杠
                except ValueError:
                    continue
            # 筛选: #开头的, 特殊筛选, 根据进程名筛选
            if not (not self.line.startswith("#") and
                    self.filter_Special(tag) and
                    self.filter_white_list(tag)):
                continue
            # 筛选: 对value排除筛选
            # pp(repr_=1)(value)
            if self.filter_other(value):
                self.valueS.append(value)
            # 筛选: key不为空才添加
            if self.filter_key(key):
                for k in re.split(r" *, *", key):
                    self.dict_[k.replace(" ", "")] = value


if __name__ == '__main__':
    s = """
#gr, gb|||group by##sql
#ha, hv|||having##sql
#aa|||aa##anki
bb|||bb##python
#cc|||quicker:runaction:cc##
dd|||123##cc
d2|||4546##any
d2|||4546##正则
"""
    s = """
bb|||bb##any
c|||a36818fe-c93a-4865-aeec-b3cba2958b50##any
"""
    procName = "Quicker"
    # procName = "pycharm64"
    ac = AutoComple(s, procName)
    ac.run()
    pp()(ac.excludeS)
    # print(*ac.excludeS, sep="\n")
    # t = Test("")python
    # for e in case_s:
    #     cc(t.filter_white_list(*e.split()[0:2], ""))
    # case_s = [
    #     "sql Code 1",
    #     "sql navicat 1",
    #     "anki anki 1",
    #     "aa bb 1",
    #     "anki navicat 0",
    # ]

    # case_s = [
    #     "quicker:runaction123 0",
    #     "123 1",
    # ]
    # for e in case_s:
    #     cc(t.filter_other(e.split()[0]))
